<html><head>
<script>

    var $ = function (id) { return document.getElementById(id) };

    var IPCalc = {
	
	re_ip  : /^(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])$/,
	re_net : /^(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])\.(1?\d{1,2}|2[0-4]\d|25[0-5])(?:\/([1-2]?\d|3[0-2]))?$/,
	
	tab : function (o, page) {
		//tabs
		var arr = document.getElementsByTagName(o.parentNode.tagName);
		for (var i=0, l=arr.length; i<l; ++i) { //>
		    arr[i].className = arr[i].className.replace('current','').trim();
		}
		o.parentNode.className += ' current';
	    
		//pages
		arr = $(page).parentNode.children;
		for (var i=0, l=arr.length; i<l; ++i) { //>
		    arr[i].className = arr[i].className.replace('hidden','').trim() + ' hidden';
		}
		$(page).className = $(page).className.replace('hidden', '').trim();
		$('result').innerHTML = '';
	    },
	    
	clean : function () {
		$('nets').value = '';
		$('ranges').value = '';
		$('start').value = '';
		$('end').value = '';
		$('result').innerHTML = '';
		return false;
	    },
	    
	ip2int : function (str) {
		var ip_ = this.re_ip.exec(str);
		if (!ip_)
		    return -1;
		return parseInt(ip_[1])*16777216 + parseInt(ip_[2])*65536 + parseInt(ip_[3])*256 + parseInt(ip_[4]);
	    },
	
	int2ip : function (_int) {
		if (_int < 0) //>
		    return '';
		var a = [ Math.floor(_int/16777216) % 256, Math.floor(_int/65536) % 256, Math.floor(_int/256) % 256, _int % 256 ];
		return a.join('.');
	    },
	
	range : function (ip_min, ip_max) {
		if (!ip_min || !ip_max)
		    return;
	
		int_min = this.ip2int(ip_min);
		if (int_min < 0) { //>
		    $('result').innerHTML = 'wrong IP "' + ip_min + '"';
		    return;
		}
		
		int_max = this.ip2int(ip_max);
		if (int_max < 0) { //>
		    $('result').innerHTML = 'wrong IP "' + ip_max + '"';
		    return;
		}
	    
		if (int_min > int_max) {
		    $('result').innerHTML = 'wrong IP range "' + ip_min + ' - ' + ip_max + '"';
		    return;
		}
		
		var out = [];
		for (var i = int_min; i <= int_max; ++i) { //>
		    str_ip = this.int2ip(i);
		    if (str_ip)
			out.push(str_ip);
		}
		return out;
	    },
	
	exec_range : function () {
	    var ip = [$('start').value.trim(), $('end').value.trim()];
	    if (!ip[0] || !ip[1])
		return;
	    
	    var ips = this.range(ip[0], ip[1]);
	    var out = '';
	    for (var j=0, l=ips.length; j<l; ++j) { //>
		out += ips[j] + '<br/>';
	    }
	    $('result').innerHTML = out;
	},
	
	exec_ranges : function () {
		var list = $('ranges').value.replace(/\r/,'').split(/\n/);
		
		var out = '';
		for (var j = 0, l = list.length; j < l; ++j) { //>
		    var ip = list[j].replace(/\s/g,'').split(/-/);
		    if (ip.length < 2) //>
			continue;
		    
		    if (!ip[0] || !ip[1])
			continue;
		    
		    var ips = this.range(ip[0], ip[1]);
		    for (var k=0, m=ips.length; k < m; ++k) { //>
			out += ips[k] + '<br/>';
		    }
		}
		$('result').innerHTML = out;
	    },
	
	exec_net : function () {
		var nets = $('nets').value.replace(/\r/,'').split(/\n/);
		var out = '';
		
		to_out = function (ip, ip_min, ip_max, mask, wildcard) {
			var ret =
			    '<div style="display: block;">'
			    + '<div style="display: inline-block; font-weight: bold; width: 160px;">' + ip + '</div>'
			    + '<input type="text" size="15" readonly="readonly" style="text-align: right;" value="'+ip_min+'" />'
			    + '&nbsp;&nbsp;-&nbsp;&nbsp;'
			    + '<input type="text" size="15" readonly="readonly" style="text-align: right;" value="'+ip_max+'" />'
			    + '&nbsp;&nbsp;&nbsp;mask:&nbsp;'
			    + '<input type="text" size="15" readonly="readonly" style="text-align: right;" value="'+mask+'" />'
			    + '&nbsp;&nbsp;&nbsp;wildcard:&nbsp;'
			    + '<input type="text" size="15" readonly="readonly" style="text-align: right;" value="'+wildcard+'" />'
			    + '</div>';
			return ret;
		    };
		
		for (var j = 0, l = nets.length; j < l; ++j) { //>
		    var ip = this.re_net.exec(nets[j].trim());
		    if (!ip) continue;
		    
		    if (!ip[5]) {
			out += to_out(ip[0], ip[0], ip[0], '255.255.255.255', '0.0.0.0');
		    } else {
			var mask = [0, 0, 0, 0];
			var wild = [0, 0, 0, 0];
			
			var imask = parseInt(ip[5]),
			    k = imask % 8,
			    n = (imask - k)/8;
			
			if (!imask)
			    continue;
			
			for (i = 0; i < 4; ++i) { //>
			    if (i < n) { //>
				wild[i] = 0;
				mask[i] = 255;
			    } else {
				wild[i] = ((i == n)? (1 << (8 - k)) - 1 : 255); //>
				mask[i] = 255 - wild[i];
			    }
			}
			var ip_min = [ ip[1] & mask[0], ip[2] & mask[1], ip[3] & mask[2], 1 | ip[4] & mask[3] ].join('.');
			var ip_max = [ ip[1] | wild[0], ip[2] | wild[1], ip[3] | wild[2], ip[4] | wild[3] ].join('.');
			
			out += to_out(ip[0], ip_min, ip_max, mask.join('.'), wild.join('.'));
		    }
		}
		$('result').innerHTML = out;
	    }
    };
    
</script>
<style>
.tabs {margin: 5px; padding: 0; padding-left: 20px; list-style-type: none;}
.tab  {border: 1px solid black; margin: 0; padding: 5px 15px; display: inline;}
.current {background-color: #e9e9e9; font-weight: bold; display: inline;}
.hidden {display: none;}
.page {border: 1px solid black; margin: 0; padding: 10px;}
.result {margin: 0; margin-top: 20px;}
FORM {margin: 0px;}
.float {float: left; margin: 0px; margin-right: 20px;}
.clear {clear: both;}
</style>
</head>
<body>

<ul class="tabs">
    <li class="tab current"><a href="#" onclick="IPCalc.tab(this, 'page1');">IP range</a></li>
    <li class="tab"><a href="#" onclick="IPCalc.tab(this, 'page2');">IP ranges</a></li>
    <li class="tab"><a href="#" onclick="IPCalc.tab(this, 'page3');">IP subnets</a></li>
</ul>

<div class="pages">
    <div id="page1" class="page">
	<form>
	    <div class="float">
		<input type="text" id="start" value="" size="15" />
		&nbsp;&nbsp;-&nbsp;&nbsp;
		<input type="text" id="end" value="" size="15" />
	    </div>
	    <div>Input IP range like 192.168.1.1 - 192.168.1.3</div>
	    <div class="clear"></div>
	    <div style="margin-top: 20px;">
		<input type="button" onClick="IPCalc.exec_range();" value="Calculate" />
		<input type="button" onClick="IPCalc.clean();" value="Clear" />
	    </div>
	    
	</form>
    </div>
    
    <div id="page2" class="page hidden">
	<form>
	    <textarea id="ranges" rows="20" cols="40" class="float"></textarea>
	    <div>Input IP ranges; one range per line like 192.168.1.0 - 192.168.2.255</div>
	    <div style="margin-top: 20px;">
		<input type="button" onClick="IPCalc.exec_ranges();" value="Calculate" />
		<input type="button" onClick="IPCalc.clean();" value="Clear" />
	    </div>
	    <div class="clear"></div>
	</form>
    </div>

    <div id="page3" class="page hidden">
	<form>
	    <textarea id="nets" rows="20" cols="40" class="float"></textarea>
	    <div>Input IP subnets; one subnet per line like 192.168.1.0/24</div>
	    <div style="margin-top: 20px;">
		<input type="button" onClick="IPCalc.exec_net();" value="Calculate" />
		<input type="button" onClick="IPCalc.clean();" value="Clear" />
	    </div>
	    <div class="clear"></div>
	</form>
    </div>
</div>

<div class="result">
    <b>Result:</b>
    <div id="result">
    </div>
</div>

</body>
</html>
